<?php

/**
 * \file
 * Classe `Member`.
 */

namespace pilar\Entities /* \cond */ ; /* \endcond */
{

/**
 * Membre d'une entité abstraite.
 *
 * \todo Découpler les membres d'entité des membres de formulaire.
 *
 * \since 25/07/2008
 * \author Matthieu OVIEDO <matthieu.oviedo@gmail.com>
 */
abstract class Member extends \object {

/**
 * Entité parente.
 */
public $parentEntity;


/**
 * Champs de données.
 */
public $fields;


/**
 * Membres locaux influencés.
 *
 * \since 07/10/2008
 */
private $_succeedingMembers;


protected function loadDefaultParams() {
 parent::loadDefaultParams();

 $this->params->define(array(
  'name' => '', // Nom.
  'caption' => '', // Intitulé.
  'genre' => 'he', // Genre.
  'inForms' => true, // Apparaît par défaut dans les formulaires ?
  'autoEvaluated' => false, // Évaluation automatique ?
  'protected' => false, // Valeurs protégées contre l'écriture ?
  'formClass' => '\\pilar\\SimpleFormMembers\\TextBox',
    // Classe par défaut pour les membres de formulaires.
  'formParams' => array(), // Configuration des membres de formulaires.
  'objectClass' => '\\pilar\\Objects\\Member',
    // Classe par défaut pour les membres d'objets.
  'inDatasheets' => true, // Apparaît par défault dans les blocs
                         // Datasheet ?
  'specialSearchMember' => false, // Membre particulier ? (Par exemple une Réference)
                                  // Si différent de false, prend le nom du membre.
  'searchFormClass' => '\\pilar\\SearchFormMembers\\TextBox'
   // Classe par default pour les membres de formulaires de recherche.
 ));
}


protected function initialize() {
 parent::initialize();

 $this->fields = array();
 $this->_succeedingMembers = array();
}


/**
 * Permet de spécifier l'entité parente du membre.
 * \param $entity Entité parente.
 */
public function setParentEntity($entity) {
 $this->parentEntity = $entity;
}


/**
 * Ajoute un champ au membre. Si un champ avec le même nom existe déjà il
 * est remplacé. Un champ ne doit être ajouté à plusieurs membres différents.
 *
 * \param $field Champ à ajouter.
 *
 * \return $this.
 */
public function addField($field) {
 $this->fields[$field->get('name')] = $field;
 $field->setParentMember($this);

 return $this;
}


/**
 * Recherche un champ en fonction de son nom.
 * \param $name Nom du champ.
 * \return Si le champ est trouvé il est retourné.
 */
public function field($name = 'value') {
 if(!isset($this->fields[$name]))
  trigger_error(
   "Le champ `{$name}` du membre `".$this->get('name')."` de l'entité `".$this->parentEntity->get('name')."` n'existe pas.",
   E_USER_ERROR
  );

 return $this->fields[$name];
}


/**
 * Ajoute un membre influencé.
 *
 * \since 07/10/2008
 */
public function addSucceedingMember($member) {
 $name = $member->get('name');
 if(!isset($this->_succeedingMembers[$name])) {
  $this->_succeedingMembers[$name] = $member;
 }
}


/**
 * Membres influencés.
 *
 * \since 07/10/2008
 * \return Membres influencés.
 */
public function succeedingMembers() {
 return $this->_succeedingMembers;
}


/**
 * Nouvelle instance d'un membre de formulaire associé au membre.
 *
 * \param $params Configuration de formulaire à appliquer.
 * \return Instance du membre de formulaire en question.
 *
 * \since 22/09/2008
 */
final public function newFormMember($params) {
 $class = $this->get('formClass');
 return new $class(array_merge(
  array(
   'name' => $this->get('name'),
   'label' => \capitalize($this->get('caption'))
  ),
  $this->defaultFormMemberParams(),
  $this->get('formParams'),
  $params
 ));
}


/**
 * Nouvelle instance d'un membre de formulaire de recherche associé au membre.
 * 
 * \param $params Configuration de formulaire à appliquer.
 * \return Instance du membre de formulaire en question.
 * \since 10/03/2009
 */
final public function newSearchFormMember($params) {
 $class = $this->get('searchFormClass');
 $sfm = new $class(array_merge(
  array(
   'name' => $this->get('name'),
   'label' => \capitalize($this->get('caption'))
  ),
  $params
 ));
 $sfm->setEntityMember($this);
 return $sfm;
}


/**
 * Configuration par défaut d'un membre de formulaire associer au membre.
 *
 * \return Configuration par défaut.
 */
protected function defaultFormMemberParams() {
 return array();
}


/**
 * Retourne la valeur d'un champ à partir des valeurs des champs d'un membre
 * de formulaire.
 *
 * \todo
 * Avoir conscience qu'à ce niveau le découplage entité / formulaires n'est pas
 * parfait. Passer par un package faisant l'interface entre les 2 niveaux
 * est plus adapté.
 *
 * \param $fm Membre de formulaire.
 * \param $f Nom du champ.
 * \return Valeur de champ à assigner.
 *
 * \since 03/12/2008
 */
public function getFieldValueFromFormMember($fm, $f = 'value') {
 // Par défaut on essaye de retourner la valeur du champ de formulaire ayant
 // le même nom :
  return $fm->value($f);
}


/**
 * Retourne la valeur d'un champ de formulaire à partir des valeurs d'un
 * membre d'objet.
 *
 * \todo Vérifier que l'objet est bien de type entité souhaité.
 *
 * \param $om Membre objet.
 * \param $f Nom du champ.
 * \return Valeur de champ à assigner.
 *
 * \since 08/12/2008
 */
public function getFormFieldValueFromObjectMember($om, $f = 'value') {
 // Par défaut on essaye de retourner la valeur du champ ayant le même
 // nom :
  return $om->field($f)->get(); 
}


/**
 * Nouvelle instance d'un membre d'objet associé au membre d'entité
 * en question.
 *
 * \return Instance du membre.
 *
 * \since 07/10/2008
 */
final public function newObjectMember() {
 $class = $this->get('objectClass');
 return new $class($this);
}


/**
 * Détermine si le membre est protégé de manière générale.
 *
 * \since 07/10/2008
 * \return TRUE / FALSE.
 */
public function isProtected() {
 return $this->get('protected');
}


/**
 * Détermine si une valeur est syntaxiquement acceptable pour un champ.*
 *
 * \since 07/10/2008
 * \return TRUE / FALSE.
 */
public function acceptsFieldValue($fieldName, $value) {
 return true; // Aucun format prérequis par défaut.
}


/**
 * Formate la valeur pour un champ donné.*
 *
 * \since 07/10/2008
 * \return Valeur formatée.
 */
public function formatFieldValue($fieldName, $value) {
 return $value; // Aucun formatage par défaut.
}


/**
 * Evalue un membre d'objet en fonction des valeurs des autres membres.*
 *
 * \since 07/10/2008
 */
public function upgradeObject($object, $self) {
 // Par défaut on ne fait rien.
}


/**
 * Permet de charger les sous-entités dans l'entité.
 *
 * \since 27/04/2009
 */
public function getSubEntities() {
 // Ne fait rien dans le cas général.
}


} // Class.

} // Namespace.

?>
